#include "SipManager.h"
#include <stdexcept>
#include <thread>
#include <chrono>
#include "StreamManager.h"

// 静态成员变量初始化
std::function<void(pjsua_acc_id)> SipManager::s_on_reg_state_cb = nullptr;
std::function<void(pjsua_acc_id, pjsua_call_id, pjsip_rx_data*)> SipManager::s_on_incoming_call_cb = nullptr;
std::function<void(pjsua_call_id, pjsip_event*)> SipManager::s_on_call_state_cb = nullptr;
std::function<void(pjsua_call_id)> SipManager::s_on_call_media_state_cb = nullptr;
std::function<pj_bool_t(pjsip_rx_data*)> SipManager::s_on_rx_request_cb = nullptr;

// 初始化静态消息处理模块
static char mod_name[] = "message_handler";
pjsip_module SipManager::s_message_module = {
    NULL, NULL,                   // prev, next
    { mod_name, 15 },             // name
    -1,                           // id
    PJSIP_MOD_PRIORITY_APPLICATION, // priority
    NULL,                         // load
    NULL,                         // start
    NULL,                         // stop
    NULL,                         // unload
    &SipManager::onRxRequest,     // on_rx_request
    NULL,                         // on_rx_response
    NULL,                         // on_tx_request
    NULL,                         // on_tx_response
    NULL,                         // on_tsx_state
};

// 获取单例实例
SipManager& SipManager::getInstance() {
    static SipManager instance;
    return instance;
}

// 构造函数
SipManager::SipManager() : acc_id(PJSUA_INVALID_ID) {
}

// 析构函数
SipManager::~SipManager() {
    shutdown();
}

// 初始化SIP库和账户
bool SipManager::initialize() {
    try {
        // 首先初始化PJLIB
        pj_status_t status;
        status = pj_init();
        if (status != PJ_SUCCESS) {
            LOG_ERROR("无法初始化PJLIB");
            return false;
        }
        
        // 使用PJSUA-LIB C API初始化
        pjsua_config ua_cfg;
        pjsua_logging_config log_cfg;
        pjsua_media_config media_cfg;
        
        // 默认配置
        pjsua_config_default(&ua_cfg);
        pjsua_logging_config_default(&log_cfg);
        pjsua_media_config_default(&media_cfg);
        
        // 设置日志级别
        log_cfg.console_level = 5;
        log_cfg.level = 5;
        
        // 完全禁用媒体子系统的配置
        media_cfg.no_vad = PJ_TRUE;  
        media_cfg.enable_ice = PJ_FALSE;
        media_cfg.enable_turn = PJ_FALSE;
        media_cfg.ec_tail_len = 0;      // 禁用回声消除
        media_cfg.snd_auto_close_time = 0;
        media_cfg.has_ioqueue = PJ_FALSE;
        media_cfg.thread_cnt = 0;        // 无媒体线程
        media_cfg.clock_rate = 8000;     // 最低时钟频率
        media_cfg.quality = 1;           // 最低质量
        media_cfg.channel_count = 1;     // 单声道
        media_cfg.ptime = 20;            // 默认帧持续时间
        
        // 设置回调函数
        ua_cfg.cb.on_incoming_call = &SipManager::onIncomingCall;
        ua_cfg.cb.on_call_media_state = &SipManager::onCallMediaState;
        ua_cfg.cb.on_call_state = &SipManager::onCallState;
        ua_cfg.cb.on_reg_state = &SipManager::onRegState;
        
        // 设置传输地址信息，解决NAT问题
        ua_cfg.stun_host = pj_str((char*)"");  // 不使用STUN
        ua_cfg.stun_srv_cnt = 0; 
        
        // 初始化PJSUA
        status = pjsua_create();
        if (status != PJ_SUCCESS) {
            LOG_ERROR("无法创建PJSUA");
            return false;
        }
        
        status = pjsua_init(&ua_cfg, &log_cfg, &media_cfg);
        if (status != PJ_SUCCESS) {
            pjsua_destroy();
            LOG_ERROR("无法初始化PJSUA");
            return false;
        }
        
        // 创建UDP传输
        pjsua_transport_config trans_cfg;
        pjsua_transport_config_default(&trans_cfg);
        trans_cfg.port = 5060;
        
        // 设置NAT类型
        Config& config = Config::getInstance();
        trans_cfg.bound_addr = pj_str((char*)"0.0.0.0");  // 绑定到所有接口
        trans_cfg.public_addr = pj_str((char*)config.PUBLIC_IP.c_str());  // 设置公网IP
        
        status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &trans_cfg, NULL);
        if (status != PJ_SUCCESS) {
            pjsua_destroy();
            LOG_ERROR("无法创建SIP传输");
            return false;
        }
        
        // 注册模块以拦截MESSAGE请求
        pjsip_endpoint *endpt = pjsua_get_pjsip_endpt();
        
        // 注册静态消息处理模块
        status = pjsip_endpt_register_module(endpt, &s_message_module);
        if (status != PJ_SUCCESS) {
            pjsua_destroy();
            LOG_ERROR("无法注册消息处理模块");
            return false;
        }
        
        // 启动PJSUA
        status = pjsua_start();
        if (status != PJ_SUCCESS) {
            pjsua_destroy();
            LOG_ERROR("无法启动PJSUA");
            return false;
        }
        
        LOG_INFO("PJSIP库初始化成功");
        return true;
    } catch (const std::exception& e) {
        LOG_ERROR("PJSIP初始化异常: " + std::string(e.what()));
        return false;
    }
}

// 注册SIP账户
bool SipManager::registerAccount() {
    try {
        Config& config = Config::getInstance();
        
        // 注册SIP账户
        pjsua_acc_config acc_cfg;
        pjsua_acc_config_default(&acc_cfg);
        
        // 设置SIP URI
        std::string idUri = "sip:" + config.DEVICE_ID + "@" + config.REALM;
        acc_cfg.id = pj_str((char*)idUri.c_str());
        LOG_INFO("SIP URI: " + idUri);
        
        // 设置注册服务器
        std::string regUri = "sip:" + config.SERVER_IP + ":" + std::to_string(config.SERVER_PORT);
        acc_cfg.reg_uri = pj_str((char*)regUri.c_str());
        LOG_INFO("注册服务器URI: " + regUri);
        
        // 不手动设置Contact头，让PJSIP自动生成
        LOG_INFO("将使用公网IP注册: " + config.PUBLIC_IP);
        
        // 设置认证信息
        acc_cfg.cred_count = 1;
        acc_cfg.cred_info[0].realm = pj_str((char*)config.REALM.c_str());
        acc_cfg.cred_info[0].scheme = pj_str((char*)"digest");
        acc_cfg.cred_info[0].username = pj_str((char*)config.DEVICE_ID.c_str());
        acc_cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
        acc_cfg.cred_info[0].data = pj_str((char*)config.PASSWORD.c_str());
        
        // 设置注册超时和重试
        acc_cfg.reg_retry_interval = 30;      // 重试间隔30秒
        acc_cfg.reg_first_retry_interval = 5; // 首次重试5秒
        acc_cfg.reg_timeout = 3600;           // 注册超时1小时
        
        // 禁用通话的媒体和视频
        acc_cfg.vid_in_auto_show = PJ_FALSE;
        acc_cfg.vid_out_auto_transmit = PJ_FALSE;
        
        // 注册账户
        pj_status_t status = pjsua_acc_add(&acc_cfg, PJ_TRUE, &acc_id);
        if (status != PJ_SUCCESS) {
            char errmsg[PJ_ERR_MSG_SIZE];
            pj_strerror(status, errmsg, sizeof(errmsg));
            LOG_ERROR("SIP账户注册失败: " + std::string(errmsg));
            return false;
        }
        
        LOG_INFO("SIP账户注册中...");
        return true;
    } catch (const std::exception& e) {
        LOG_ERROR("SIP账户注册异常: " + std::string(e.what()));
        return false;
    }
}

// 发送SIP消息
bool SipManager::sendMessage(const std::string& target_uri, const std::string& content, const std::string& content_type) {
    try {
        // 将C++字符串转换为PJSIP字符串
        pj_str_t to_uri = pj_str((char*)target_uri.c_str());
        pj_str_t content_str = pj_str((char*)content.c_str());
        
        // 准备消息数据
        pjsua_msg_data msg_data;
        pjsua_msg_data_init(&msg_data);
        
        // 设置消息头部和内容类型
        char content_type_buf[128];
        snprintf(content_type_buf, sizeof(content_type_buf), "%s", content_type.c_str());
        msg_data.content_type = pj_str(content_type_buf);
        
        // 发送即时消息
        pj_status_t status = pjsua_im_send(acc_id, &to_uri, NULL, &content_str, &msg_data, NULL);
        
        if (status != PJ_SUCCESS) {
            char errmsg[PJ_ERR_MSG_SIZE];
            pj_strerror(status, errmsg, sizeof(errmsg));
            LOG_ERROR("发送消息失败，错误: " + std::string(errmsg));
            return false;
        } else {
            LOG_INFO("消息已发送");
            return true;
        }
    } catch (const std::exception& e) {
        LOG_ERROR("发送SIP消息异常: " + std::string(e.what()));
        return false;
    }
}

// 关闭并清理SIP资源
void SipManager::shutdown() {
    if (pjsua_get_state() > PJSUA_STATE_NULL) {
        pjsua_destroy();
        LOG_INFO("PJSIP资源已释放");
    }
}

// 获取账户ID
pjsua_acc_id SipManager::getAccountId() const {
    return acc_id;
}

// 设置回调函数
void SipManager::setCallbacks(
    std::function<void(pjsua_acc_id)> on_reg_state_cb,
    std::function<void(pjsua_acc_id, pjsua_call_id, pjsip_rx_data*)> on_incoming_call_cb,
    std::function<void(pjsua_call_id, pjsip_event*)> on_call_state_cb,
    std::function<void(pjsua_call_id)> on_call_media_state_cb,
    std::function<pj_bool_t(pjsip_rx_data*)> on_rx_request_cb
) {
    s_on_reg_state_cb = on_reg_state_cb;
    s_on_incoming_call_cb = on_incoming_call_cb;
    s_on_call_state_cb = on_call_state_cb;
    s_on_call_media_state_cb = on_call_media_state_cb;
    s_on_rx_request_cb = on_rx_request_cb;
}

// 注册状态回调
void SipManager::onRegState(pjsua_acc_id acc_id) {
    if (s_on_reg_state_cb) {
        s_on_reg_state_cb(acc_id);
    } else {
        pjsua_acc_info info;
        pjsua_acc_get_info(acc_id, &info);
        
        if (info.status == 200 || info.status == 0) {
            LOG_INFO("SIP注册成功");
        } else {
            LOG_WARN("SIP注册失败或注销，状态码: " + std::to_string(info.status));
        }
    }
}

// 处理传入呼叫
void SipManager::onIncomingCall(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata) {
    // 绕过默认的媒体初始化，直接使用自定义处理
    try {
        if (s_on_incoming_call_cb) {
            // 如果设置了自定义回调，先尝试使用它
            s_on_incoming_call_cb(acc_id, call_id, rdata);
            return;
        }
        
        LOG_INFO("收到呼叫请求 ID: " + std::to_string(call_id) + " 账户ID: " + std::to_string(acc_id));
        
        // 检查是否有SDP
        if (!rdata || !rdata->msg_info.msg || !rdata->msg_info.msg->body) {
            LOG_ERROR("INVITE请求中没有SDP正文");
            pjsua_call_hangup(call_id, 400, NULL, NULL);
            return;
        }
        
        // 获取并解析SDP
        pjsip_msg* invite_msg = rdata->msg_info.msg;
        std::string sdp_offer((char*)invite_msg->body->data, invite_msg->body->len);
        LOG_INFO("收到SDP Offer: \n" + sdp_offer);
        
        // 使用StreamManager解析SDP
        StreamManager& streamManager = StreamManager::getInstance();
        if (!streamManager.parseSdpAndSetParams(sdp_offer)) {
            LOG_ERROR("解析SDP失败");
            pjsua_call_hangup(call_id, 488, NULL, NULL);
            return;
        }
        
        std::string sdp_answer = streamManager.generateSdpAnswer();
        LOG_INFO("生成SDP应答:\n" + sdp_answer);
        
        // 自定义消息数据
        pjsua_msg_data msg_data;
        pjsua_msg_data_init(&msg_data);
        
        // 设置SDP类型和内容
        msg_data.content_type = pj_str((char*)"application/sdp");
        msg_data.msg_body = pj_str((char*)sdp_answer.c_str());
        
        // 接受呼叫，直接发送200 OK
        LOG_INFO("接受呼叫并提供SDP应答");
        pj_status_t status = pjsua_call_answer(call_id, 200, NULL, &msg_data);
        
        if (status != PJ_SUCCESS) {
            LOG_ERROR("接受呼叫失败，错误码: " + std::to_string(status));
            pjsua_call_hangup(call_id, 500, NULL, NULL);
            return;
        }
        
        LOG_INFO("呼叫已接受，等待媒体建立");
        
        // 等待一小段时间，确保SDP交换完成
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        
        // 启动FFmpeg推流
        if (!streamManager.startStreaming()) {
            LOG_ERROR("启动推流失败");
            pjsua_call_hangup(call_id, 500, NULL, NULL);
            return;
        }
        
        LOG_INFO("推流已启动");
        
    } catch (const std::exception& e) {
        LOG_ERROR("处理呼入呼叫时异常: " + std::string(e.what()));
        pjsua_call_hangup(call_id, 500, NULL, NULL);
    }
}

// 呼叫状态回调
void SipManager::onCallState(pjsua_call_id call_id, pjsip_event *e) {
    if (s_on_call_state_cb) {
        s_on_call_state_cb(call_id, e);
    } else {
        pjsua_call_info ci;
        pjsua_call_get_info(call_id, &ci);
        
        // 打印呼叫状态
        char state_str[100];
        pj_ansi_snprintf(state_str, sizeof(state_str), "%.*s", (int)ci.state_text.slen, ci.state_text.ptr);
        LOG_INFO("呼叫状态: " + std::string(state_str));
        
        // 如果呼叫断开，停止推流
        if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
            LOG_INFO("呼叫已断开，停止推流");
            StreamManager::getInstance().stopStreaming();
        }
    }
}

// 媒体状态回调
void SipManager::onCallMediaState(pjsua_call_id call_id) {
    if (s_on_call_media_state_cb) {
        s_on_call_media_state_cb(call_id);
    } else {
        LOG_INFO("媒体状态改变，呼叫ID: " + std::to_string(call_id));
    }
}

// 接收SIP MESSAGE请求的处理函数
pj_bool_t SipManager::onRxRequest(pjsip_rx_data *rdata) {
    if (s_on_rx_request_cb) {
        return s_on_rx_request_cb(rdata);
    } else {
        // 检查是否是MESSAGE请求
        const pj_str_t message_method = pj_str((char*)"MESSAGE");
        if (pj_strcmp(&rdata->msg_info.msg->line.req.method.name, &message_method) == 0) {
            LOG_INFO("收到SIP MESSAGE请求，但未设置处理回调");
            
            // 回复200 OK
            pjsip_endpt_respond_stateless(pjsua_get_pjsip_endpt(), rdata, 200, NULL, NULL, NULL);
            return PJ_TRUE;
        }
    }
    
    // 返回PJ_FALSE表示未处理，继续传递给其他模块
    return PJ_FALSE;
}

// 处理传入的呼叫请求 - 由Application类调用
bool SipManager::handleIncomingCall(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata) {
    LOG_INFO("处理呼叫请求 ID: " + std::to_string(call_id) + " 账户ID: " + std::to_string(acc_id));
    
    try {
        // 检查是否有SDP
        if (!rdata) {
            LOG_ERROR("错误: INVITE请求数据为空");
            return false;
        }
        
        if (!rdata->msg_info.msg) {
            LOG_ERROR("错误: INVITE消息为空");
            return false;
        }
        
        if (!rdata->msg_info.msg->body) {
            LOG_ERROR("错误: INVITE请求中没有SDP正文");
            return false;
        }
        
        // 获取INVITE请求
        pjsip_msg* invite_msg = rdata->msg_info.msg;
        
        // 获取From和To头信息
        pjsip_from_hdr* from_hdr = (pjsip_from_hdr*)pjsip_msg_find_hdr(invite_msg, PJSIP_H_FROM, NULL);
        pjsip_to_hdr* to_hdr = (pjsip_to_hdr*)pjsip_msg_find_hdr(invite_msg, PJSIP_H_TO, NULL);
        
        std::string from_uri;
        std::string to_uri;
        
        if (from_hdr && from_hdr->uri) {
            char uri_str[PJSIP_MAX_URL_SIZE];
            int len = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, from_hdr->uri, uri_str, sizeof(uri_str));
            if (len > 0) {
                from_uri = std::string(uri_str, len);
                LOG_INFO("呼叫来自: " + from_uri);
            }
        }
        
        if (to_hdr && to_hdr->uri) {
            char uri_str[PJSIP_MAX_URL_SIZE];
            int len = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, to_hdr->uri, uri_str, sizeof(uri_str));
            if (len > 0) {
                to_uri = std::string(uri_str, len);
                LOG_INFO("呼叫目标: " + to_uri);
            }
        }
        
        // 判断目标URI是否包含我们的通道ID，而不是设备ID
        std::string device_id = Config::getInstance().getDeviceId();
        std::string channel_id = Config::getInstance().getChannelId();
        
        // 检查目标URI中是否包含我们的通道ID - 这很重要，因为平台可能使用通道ID而不是设备ID来发起呼叫
        if (to_uri.find(channel_id) != std::string::npos) {
            LOG_INFO("检测到针对通道ID的呼叫，继续处理...");
            // 呼叫目标是我们的通道，继续处理
        } else if (to_uri.find(device_id) != std::string::npos) {
            LOG_INFO("检测到针对设备ID的呼叫，继续处理...");
            // 呼叫目标是我们的设备，继续处理
        } else {
            LOG_WARN("呼叫目标不是我们的设备ID或通道ID，可能是配置错误");
            // 如果既不是设备ID也不是通道ID，仍然尝试处理，因为可能是URI格式问题
        }
        
        // 获取并解析SDP
        std::string sdp_offer((char*)invite_msg->body->data, invite_msg->body->len);
        LOG_INFO("收到SDP Offer: \n" + sdp_offer);
        
        // 使用StreamManager解析SDP并设置参数
        StreamManager& streamManager = StreamManager::getInstance();
        if (!streamManager.parseSdpAndSetParams(sdp_offer)) {
            LOG_ERROR("解析SDP失败");
            return false;
        }
        
        // 构建符合国标平台期望的SDP应答
        std::string sdp_answer = streamManager.generateSdpAnswer();
        
        LOG_INFO("SDP应答:\n" + sdp_answer);
        
        // 接受呼叫
        pjsua_msg_data msg_data;
        pjsua_msg_data_init(&msg_data);
        
        // 设置SDP类型和内容
        msg_data.content_type = pj_str((char*)"application/sdp");
        msg_data.msg_body = pj_str((char*)sdp_answer.c_str());
        
        // 发送200 OK应答
        LOG_INFO("正在接受呼叫...");
        pj_status_t status = pjsua_call_answer(call_id, 200, NULL, &msg_data);
        if (status != PJ_SUCCESS) {
            char errmsg[PJ_ERR_MSG_SIZE];
            pj_strerror(status, errmsg, sizeof(errmsg));
            std::string errstr = std::string(errmsg);
            LOG_ERROR("接受呼叫失败，错误码: " + std::to_string(status) + ", 错误信息: " + errstr);
            return false;
        }
        
        LOG_INFO("成功接受呼叫，SDP应答已发送");
        
        // 等待确保SDP交换完成
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        
        // 启动推流
        if (!streamManager.startStreaming()) {
            LOG_ERROR("启动推流失败");
            return false;
        }
        
        return true;
    } catch (const std::exception& e) {
        LOG_ERROR("处理呼入请求时出错: " + std::string(e.what()));
        return false;
    }
} 